#include "persistentdata.h"
#include <bcm/bcm.h>
#include <iostream>


template <typename T, typename S>
void displayParameter(cnc::base::Parameter *param)
{
	T value;
	if (param->get(&value))
		std::cout << static_cast<S>(value) << std::endl;
	else
		std::cout << "---" << std::endl;
}

int main()
{
	bcm::ComponentManager &compMgr = bcm::ComponentManager::instance();
	switch (compMgr.loadComponent(TEXT("database.dll"))) {
	case bcm::LC_NODLL:
		std::cout << "Could not load database.dll." << std::endl;
		return 1;
	case bcm::LC_NOCOMPONENT:
		std::cout << "No component contained in database.dll." << std::endl;
		return 1;
	case bcm::LC_ALREADYUSED:
		std::cout << "Component \"db\" already registered." << std::endl;
		return 1;
	case bcm::LC_OK:
		std::cout << "Component \"db\" properly loaded from database.dll." << std::endl;
		break;
	}
	bcm::Component *component;
	switch (compMgr.getComponent("db", &component)) {
	case bcm::GC_UNREGISTERED:
		std::cout << "Component \"db\" was never registered." << std::endl;
		return 1;
	case bcm::GC_NOCOMPONENT:
		std::cout << "Component \"db\" not available in DLL." << std::endl;
		return 1;
	case bcm::GC_INCOMPLETE:
		std::cout << "Component \"db\" incomplete." << std::endl;
		return 1;
	case bcm::GC_OK:
		std::cout << "Component \"db\" properly loaded." << std::endl;
		break;
	}
	bcm::Interface *iface;
	iface = component->getInterface("pdata");
	if (iface == 0) {
		std::cout << "Could not get interface PersistentData." << std::endl;
		return 1;
	}
	cnc::base::PersistentData *pd = dynamic_cast<cnc::base::PersistentData *>(iface);
	if (iface == 0) {
		std::cout << "Retrieved interface is not PersistentData." << std::endl;
		return 1;
	}
	cnc::base::Parameter *param;
	pd->addParameter("hello", cnc::base::DT_UINT8);
	param = pd->getParameter("hello");
	if (param == 0) {
		std::cout << "Could not retrieve parameter." << std::endl;
		return 1;
	}
	param->set(static_cast<uint8_t>(7));
	pd->save("test.db");
	pd->load("test.db");
	int i = 0;
	for (const char *paramName = pd->getFirstParameterName();
		paramName != 0;
		paramName = pd->getNextParameterName(), i++) {
			std::cout << i << ". " << paramName << ": ";
			param = pd->getParameter(paramName);
			switch (param->getDataType()) {
			case cnc::base::DT_INT8:
				displayParameter<int8_t, int16_t>(param);
				break;
			case cnc::base::DT_UINT8:
				displayParameter<uint8_t, uint16_t>(param);
				break;
			case cnc::base::DT_INT16:
				displayParameter<int16_t, int16_t>(param);
				break;
			case cnc::base::DT_UINT16:
				displayParameter<uint16_t, uint16_t>(param);
				break;
			case cnc::base::DT_INT32:
				displayParameter<int32_t, int32_t>(param);
				break;
			case cnc::base::DT_UINT32:
				displayParameter<uint32_t, uint32_t>(param);
				break;
			case cnc::base::DT_INT64:
				displayParameter<int64_t, int64_t>(param);
				break;
			case cnc::base::DT_UINT64:
				displayParameter<uint64_t, uint64_t>(param);
				break;
			case cnc::base::DT_FLOAT32:
				displayParameter<float, float>(param);
				break;
			case cnc::base::DT_FLOAT64:
				displayParameter<double, double>(param);
				break;
			default:
				std::cout << "unsupported" << std::endl;
			}
	}
	return 0;
}

